#Flash example
#Author: Bei Yang
#Date: 6-2-09
#Description: Simple example of safe message
#passing to and from flash using a windows activeX control
#Since this depends on ActiveX controls, you can only use this on
#windows.
#
#Disclaimer: Use at your own risk

#depending on your install you may have either delete or modify the
#following 2 lines
#import wxversion
#wxversion.select('2.8')

#import the needed libraries
import wx
from wx.lib.flashwin import FlashWindow

#which file to load
#change this to a path you want.
DEFAULT_MOVIE_TO_LOAD = "F:\\jxgame\\flash\\py\\Test1.swf"

#An object, it really doesn't need to be, but it sure makes it easier
#Many people like to inherit a frame... it does make it easier to then
#drop your code into another wx app afterwards... but that's confusing
#in an example.  If your doing it for real, it's probably a good idea.
class FlashExample:
  def __init__(self, parent, sort):
    self.makeWxWindow(parent, sort)
    self.loadMovie(DEFAULT_MOVIE_TO_LOAD)

    return

  # ----------- Initialization methods --------------------------------
  def makeWxWindow(self, parent, sort):
    """
    Initialization for the making a window and some sizers to auto-
    matically exand the window to fit the flash app
    """
    self.rootPanel = wx.Panel(parent, sort)

    #make a flash window
    self.flashWin = FlashWindow(self.rootPanel)
    #make a button and a text box
    self.txtBox = wx.TextCtrl(self.rootPanel, wx.NewId())
    self.btSend = wx.Button(self.rootPanel, wx.NewId(), "Send Aove To Flash")
    
    #place them all in a sizer and vertically lay the out... not pretty but simple
    self.flashSizer = wx.BoxSizer(wx.VERTICAL)
    self.flashSizer.Add(self.flashWin,proportion=1, flag=wx.EXPAND)
    self.flashSizer.Add(self.txtBox, proportion=0.3, flag=wx.EXPAND|wx.ALL, border=2)
    self.flashSizer.Add(self.btSend, proportion=0.3, flag=wx.EXPAND|wx.ALL, border=2)

    #actually set the sizer to the root panel
    self.rootPanel.SetSizer(self.flashSizer)
    self.rootPanel.SetAutoLayout(True)

    #now that the flash component has been created we can tell the com object
    #to use this class as the event sink.  The flash activeX control has,
    #FlashCall, FSCommand, OnProgress, and OnReadyStateChange as events.
    #We just need to make functions that have the same name and they'll get
    #called when the event is triggered.
    self.flashWin.AddEventSink(self)

    #now for wxEvent handling.
    self.rootPanel.Bind(wx.EVT_BUTTON, self.sendToFlashHandler, self.btSend)
    return

  def loadMovie(self, moviePath):
    """
    This can be called from the outside. It just loads a new swf movie.
    And then sets the window size to the newly load flash app size.
    """
    self.flashWin.LoadMovie(0, moviePath)
    return

  # ----------- Event Sink handlers ------------------------------------------
  def FlashCall(self, xmlStr):
    """
    This is an event sink handler.  The ActiveX control has several events,
    when they get triggered, they simply call a function with the same name
    In this case, we're catching the "FlashCall" event.  The argument will be
    an xml string from flash specifying which function should be called and
    which arguments to give it.  Docs for the xml format can be found at:
    http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7caf.html
    """
    print "FlashCall:", xmlStr

  # ----------- WxPython Event handlers --------------------------------------
  def sendToFlashHandler(self, btEvent):
    """
    Does handling of the "send to flash" button event.  When this key is pressed
    we'll take the string from the text box and pass it onto flash
    """
    sendStr = self.txtBox.GetValue()
    #This is the string that was passed to ExternalInterface in flash. See
    #the .fla actionscript.
    flashFunctionName = "ExternalReceiver"
    #like the flashCall, calling a flash function also requires an xml string
    #we'll just generate one really quick.  Usually I'd probably do an automatic
    #xml parser/caller, but for clarity sake, we'll just do our own really quick here
    xmlStr = "<invoke name=\"" + flashFunctionName + "\" returntype=\"xml\">"
    xmlStr += "<arguments>"
    xmlStr += "<string>" + sendStr + "</string>"
    xmlStr += "</arguments>"
    xmlStr += "</invoke>"
    
    #now to actually invoke it
    rValue = self.flashWin.ctrl.CallFunction(xmlStr)
    
    #you'll notice that you can get return values too.  This return value will
    #be in the same xml format.  For this example, we'll just print it.
    print "XML return value: ", rValue

#basic wx stuff
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "Flash Example")
example = FlashExample(frame, -1)
frame.Show(True)
app.MainLoop()




